Export Xen s/w perfctrs to DOM0 via new 'xenperf' utility.
3f5ef5a2dTZP0nnsFoeq2jRf3mWDDg tools/misc/xen-clone.README
405eedf6_nnNhFQ1I85lhCkLK6jFGA tools/misc/xencons
40c9c4697z76HDfkCLdMhmaEwzFoNQ tools/misc/xend
+41adc641dV-0cDLSyzMs5BT8nL7v3Q tools/misc/xenperf.c
4107986eMWVdBoz4tXYoOscpN_BCYg tools/misc/xensv
4056f5155QYZdsk-1fLdjsZPFTnlhg tools/misc/xensymoops
40cf2937dqM1jWW87O5OoOYND8leuA tools/misc/xm
tools/check/.*
tools/libxc/xen/*
tools/misc/miniterm/miniterm
-tools/misc/xen_cpuperf
+tools/misc/xenperf
tools/vnet/gc
tools/vnet/gc*/*
tools/vnet/vnet-module/.tmp_versions/*
unsigned int initial_memkb);
int xc_domain_setmaxmem(int xc_handle,
- u32 domid,
- unsigned int max_memkb);
+ u32 domid,
+ unsigned int max_memkb);
int xc_domain_setvmassist(int xc_handle,
u32 domid,
unsigned int cmd,
unsigned int type);
+typedef dom0_perfc_desc_t xc_perfc_desc_t;
+/* IMPORTANT: The caller is responsible for mlock()'ing the @desc array. */
+int xc_perfc_control(int xc_handle,
+ u32 op,
+ xc_perfc_desc_t *desc);
void *xc_map_foreign_range(int xc_handle, u32 dom,
int size, int prot,
op.cmd = DOM0_SCHED_ID;
op.interface_version = DOM0_INTERFACE_VERSION;
- if((ret = do_dom0_op(xc_handle, &op))) return ret;
+ if ( (ret = do_dom0_op(xc_handle, &op)) != 0 )
+ return ret;
*sched_id = op.u.sched_id.sched_id;
return 0;
}
+int xc_perfc_control(int xc_handle,
+ u32 op,
+ xc_perfc_desc_t *desc)
+{
+ int rc;
+ dom0_op_t dop;
+
+ dop.cmd = DOM0_PERFCCONTROL;
+ dop.u.perfccontrol.op = op;
+ dop.u.perfccontrol.desc = desc;
+
+ rc = do_dom0_op(xc_handle, &dop);
+
+ return (rc == 0) ? dop.u.perfccontrol.nr_counters : rc;
+}
include $(XEN_ROOT)/tools/Make.defs
CC = gcc
-CFLAGS = -Wall -O3
+CFLAGS = -Wall -Werror -O3
INCLUDES += -I $(XEN_XC)
INCLUDES += -I $(XEN_LIBXC)
-INCLUDES += -I $(XEN_LIBXUTIL)
-
-CFLAGS += $(INCLUDES)
+CFLAGS += $(INCLUDES)
HDRS = $(wildcard *.h)
-SRCS = $(wildcard *.c)
-OBJS = $(patsubst %.c,%.o,$(SRCS))
-TARGETS =
+TARGETS = xenperf
INSTALL_BIN = $(TARGETS) xencons
-INSTALL_SBIN = netfix xm xend xensv
+INSTALL_SBIN = netfix xm xend xensv xenperf
all: $(TARGETS)
$(MAKE) -C miniterm
clean:
$(RM) *.o $(TARGETS) *~
- $(MAKE) -C miniterm clean
+ $(MAKE) -C miniterm clean
%: %.c $(HDRS) Makefile
- $(CC) $(CFLAGS) -o $@ $<
+ $(CC) $(CFLAGS) -o $@ $< -L$(XEN_LIBXC) -lxc -L$(XEN_LIBXUTIL) -lxutil
--- /dev/null
+/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
+ ****************************************************************************
+ * (C) 2004 - Rolf Neugebauer - Intel Research Cambridge
+ ****************************************************************************
+ *
+ * File: xenperf.c
+ * Author: Rolf Neugebauer (rolf.neugebauer@intel.com)
+ * Date: Nov 2004
+ *
+ * Description:
+ */
+
+
+#include <xc.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <string.h>
+
+int main(int argc, char *argv[])
+{
+ int i, j, xc_handle;
+ xc_perfc_desc_t *pcd;
+ unsigned int num, sum, reset = 0;
+
+ if ( argc > 1 )
+ {
+ char *p = argv[1];
+ if ( (*p++ == '-') && (*p == 'r') )
+ reset = 1;
+ else
+ {
+ printf("%s: [-r]\n", argv[0]);
+ printf("no args: print xen performance counters\n");
+ printf(" -r : reset xen performance counters\n");
+ return 0;
+ }
+ }
+
+ if ( (xc_handle = xc_interface_open()) == -1 )
+ {
+ fprintf(stderr, "Error opening xc interface: %d (%s)\n",
+ errno, strerror(errno));
+ return 1;
+ }
+
+ if ( reset )
+ {
+ if ( xc_perfc_control(xc_handle, DOM0_PERFCCONTROL_OP_RESET,
+ NULL) < 0 )
+ {
+ fprintf(stderr, "Error reseting performance counters: %d (%s)\n",
+ errno, strerror(errno));
+ return 1;
+ }
+
+ return 0;
+ }
+
+
+ if ( (num = xc_perfc_control(xc_handle, DOM0_PERFCCONTROL_OP_QUERY,
+ NULL)) < 0 )
+ {
+ fprintf(stderr, "Error getting number of perf counters: %d (%s)\n",
+ errno, strerror(errno));
+ return 1;
+ }
+
+ pcd = malloc(sizeof(*pcd) * num);
+
+ if ( mlock(pcd, sizeof(*pcd) * num) != 0 )
+ {
+ fprintf(stderr, "Could not mlock descriptor buffer: %d (%s)\n",
+ errno, strerror(errno));
+ exit(-1);
+ }
+
+ if ( xc_perfc_control(xc_handle, DOM0_PERFCCONTROL_OP_QUERY, pcd) <= 0 )
+ {
+ fprintf(stderr, "Error getting perf counter description: %d (%s)\n",
+ errno, strerror(errno));
+ return 1;
+ }
+
+ munlock(pcd, sizeof(*pcd) * num);
+
+ for ( i = 0; i < num; i++ )
+ {
+ printf ("%-35s ", pcd[i].name);
+
+ sum = 0;
+ for ( j = 0; j < pcd[i].nr_vals; j++ )
+ sum += pcd[i].vals[j];
+ printf ("T=%10u ", (unsigned int)sum);
+
+ for ( j = 0; j < pcd[i].nr_vals; j++ )
+ printf(" %10u", (unsigned int)pcd[i].vals[j]);
+
+ printf("\n");
+ }
+
+ return 0;
+}
u32 type_info;
domid_t domid;
- perfc_incrc(calls_to_mmu_update);
- perfc_addc(num_page_updates, count);
-
cleanup_writable_pagetable(d, PTWR_CLEANUP_ACTIVE | PTWR_CLEANUP_INACTIVE);
/*
}
}
+ perfc_incrc(calls_to_mmu_update);
+ perfc_addc(num_page_updates, count);
+
if ( unlikely(!array_access_ok(VERIFY_READ, ureqs, count, sizeof(req))) )
{
rc = -EFAULT;
}
break;
+#ifdef PERF_COUNTERS
+ case DOM0_PERFCCONTROL:
+ {
+ extern int perfc_control(dom0_perfccontrol_t *);
+ ret = perfc_control(&op->u.perfccontrol);
+ copy_to_user(u_dom0_op, op, sizeof(*op));
+ }
+ break;
+#endif
+
default:
ret = arch_do_dom0_op(op,u_dom0_op);
#include <xen/time.h>
#include <xen/perfc.h>
#include <xen/keyhandler.h>
+#include <public/dom0_ops.h>
+#include <asm/uaccess.h>
#undef PERFCOUNTER
#undef PERFCOUNTER_CPU
s_time_t now = NOW();
atomic_t *counters = (atomic_t *)&perfcounters;
- printk("Xen performance counters RESET (now = 0x%08X:%08X)\n",
- (u32)(now>>32), (u32)now);
+ if ( key != '\0' )
+ printk("Xen performance counters RESET (now = 0x%08X:%08X)\n",
+ (u32)(now>>32), (u32)now);
/* leave STATUS counters alone -- don't reset */
}
}
+static dom0_perfc_desc_t perfc_d[NR_PERFCTRS];
+static int perfc_init = 0;
+static int perfc_copy_info(dom0_perfc_desc_t *desc)
+{
+ unsigned int i, j;
+ atomic_t *counters = (atomic_t *)&perfcounters;
+
+ if ( desc == NULL )
+ return 0;
+
+ /* We only copy the name and array-size information once. */
+ if ( !perfc_init )
+ {
+ for ( i = 0; i < NR_PERFCTRS; i++ )
+ {
+ strncpy(perfc_d[i].name, perfc_info[i].name,
+ sizeof(perfc_d[i].name));
+ perfc_d[i].name[sizeof(perfc_d[i].name)-1] = '\0';
+
+ switch ( perfc_info[i].type )
+ {
+ case TYPE_SINGLE:
+ case TYPE_S_SINGLE:
+ perfc_d[i].nr_vals = 1;
+ break;
+ case TYPE_CPU:
+ case TYPE_S_CPU:
+ perfc_d[i].nr_vals = smp_num_cpus;
+ break;
+ case TYPE_ARRAY:
+ case TYPE_S_ARRAY:
+ perfc_d[i].nr_vals = perfc_info[i].nr_elements;
+ break;
+ }
+
+ if ( perfc_d[i].nr_vals > ARRAY_SIZE(perfc_d[i].vals) )
+ perfc_d[i].nr_vals = ARRAY_SIZE(perfc_d[i].vals);
+ }
+
+ perfc_init = 1;
+ }
+
+ /* We gather the counts together every time. */
+ for ( i = 0; i < NR_PERFCTRS; i++ )
+ {
+ switch ( perfc_info[i].type )
+ {
+ case TYPE_SINGLE:
+ case TYPE_S_SINGLE:
+ perfc_d[i].vals[0] = atomic_read(&counters[0]);
+ counters += 1;
+ break;
+ case TYPE_CPU:
+ case TYPE_S_CPU:
+ for ( j = 0; j < perfc_d[i].nr_vals; j++ )
+ perfc_d[i].vals[j] = atomic_read(&counters[j]);
+ counters += NR_CPUS;
+ break;
+ case TYPE_ARRAY:
+ case TYPE_S_ARRAY:
+ for ( j = 0; j < perfc_d[i].nr_vals; j++ )
+ perfc_d[i].vals[j] = atomic_read(&counters[j]);
+ counters += perfc_info[i].nr_elements;
+ break;
+ }
+ }
+
+ return (copy_to_user(desc, perfc_d, NR_PERFCTRS * sizeof(*desc)) ?
+ -EFAULT : 0);
+}
+
+/* Dom0 control of perf counters */
+int perfc_control(dom0_perfccontrol_t *pc)
+{
+ static spinlock_t lock = SPIN_LOCK_UNLOCKED;
+ u32 op = pc->op;
+ int rc;
+
+ pc->nr_counters = NR_PERFCTRS;
+
+ spin_lock(&lock);
+
+ switch ( op )
+ {
+ case DOM0_PERFCCONTROL_OP_RESET:
+ perfc_copy_info(pc->desc);
+ perfc_reset(0);
+ rc = 0;
+ break;
+
+ case DOM0_PERFCCONTROL_OP_QUERY:
+ perfc_copy_info(pc->desc);
+ rc = 0;
+ break;
+
+ default:
+ rc = -EINVAL;
+ break;
+ }
+
+ spin_unlock(&lock);
+
+ return rc;
+}
u32 __pad1;
} PACKED dom0_read_memtype_t; /* 32 bytes */
+/* Interface for controlling Xen software performance counters. */
+#define DOM0_PERFCCONTROL 34
+/* Sub-operations: */
+#define DOM0_PERFCCONTROL_OP_RESET 1 /* Reset all counters to zero. */
+#define DOM0_PERFCCONTROL_OP_QUERY 2 /* Get perfctr information. */
+typedef struct {
+ u8 name[80]; /* 0: name of perf counter */
+ u32 nr_vals; /* 80: number of values for this counter */
+ u32 vals[64]; /* 84: array of values */
+} PACKED dom0_perfc_desc_t; /* 340 bytes */
+typedef struct {
+ /* IN variables. */
+ u32 op; /* 0: DOM0_PERFCCONTROL_OP_??? */
+ /* OUT variables. */
+ u32 nr_counters; /* 4: number of counters */
+ dom0_perfc_desc_t *desc; /* 8: counter information (or NULL) */
+ MEMORY_PADDING;
+} PACKED dom0_perfccontrol_t; /* 16 bytes */
+
typedef struct {
u32 cmd; /* 0 */
u32 interface_version; /* 4 */ /* DOM0_INTERFACE_VERSION */
dom0_add_memtype_t add_memtype;
dom0_del_memtype_t del_memtype;
dom0_read_memtype_t read_memtype;
+ dom0_perfccontrol_t perfccontrol;
} PACKED u;
} PACKED dom0_op_t; /* 80 bytes */